<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Camera Motion Estimation</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li><li class="navelem"><a class="el" href="../../de/d7c/tutorial_table_of_content_sfm.html">Structure From Motion</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Camera Motion Estimation </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<p>In this tutorial you will learn how to use the reconstruction api for camera motion estimation:</p>
<ul>
<li>Load a file with the tracked 2d points and build the container over all the frames.</li>
<li>Run libmv reconstruction pipeline.</li>
<li>Show obtained results using Viz.</li>
</ul>
<h2>Code </h2>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d3/df9/sfm_8hpp.html">opencv2/sfm.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d0/d7e/viz_8hpp.html">opencv2/viz.hpp</a>&gt;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;fstream&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>std;</div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../db/db0/namespacecv_1_1sfm.html">cv::sfm</a>;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> help() {</div><div class="line">  cout</div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;\n------------------------------------------------------------------\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; This program shows the camera trajectory reconstruction capabilities\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; in the OpenCV Structure From Motion (SFM) module.\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; Usage:\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        example_sfm_trajectory_reconstruction &lt;path_to_tracks_file&gt; &lt;f&gt; &lt;cx&gt; &lt;cy&gt;\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; where: is the tracks file absolute path into your system. \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        The file must have the following format: \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        row1 : x1 y1 x2 y2 ... x36 y36 for track 1\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        row2 : x1 y1 x2 y2 ... x36 y36 for track 2\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        etc\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        i.e. a row gives the 2D measured position of a point as it is tracked\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        through frames 1 to 36.  If there is no match found in a view then x\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        and y are -1.\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        Each row corresponds to a different point.\n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot; \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        f  is the focal length in pixels. \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        cx is the image principal point x coordinates in pixels. \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;        cy is the image principal point y coordinates in pixels. \n&quot;</span></div><div class="line">      &lt;&lt; <span class="stringliteral">&quot;------------------------------------------------------------------\n\n&quot;</span></div><div class="line">      &lt;&lt; endl;</div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">/* Build the following structure data</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *            frame1           frame2           frameN</span></div><div class="line"><span class="comment"> *  track1 | (x11,y11) | -&gt; | (x12,y12) | -&gt; | (x1N,y1N) |</span></div><div class="line"><span class="comment"> *  track2 | (x21,y11) | -&gt; | (x22,y22) | -&gt; | (x2N,y2N) |</span></div><div class="line"><span class="comment"> *  trackN | (xN1,yN1) | -&gt; | (xN2,yN2) | -&gt; | (xNN,yNN) |</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *  In case a marker (x,y) does not appear in a frame its</span></div><div class="line"><span class="comment"> *  values will be (-1,-1).</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> parser_2D_tracks(<span class="keyword">const</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> &amp;_filename, std::vector&lt;Mat&gt; &amp;points2d )</div><div class="line">{</div><div class="line">  ifstream myfile(_filename.c_str());</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span> (!myfile.is_open())</div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;Unable to read file: &quot;</span> &lt;&lt; _filename &lt;&lt; endl;</div><div class="line">    exit(0);</div><div class="line"></div><div class="line">  } <span class="keywordflow">else</span> {</div><div class="line"></div><div class="line">    <span class="keywordtype">double</span> x, y;</div><div class="line">    <span class="keywordtype">string</span> line_str;</div><div class="line">    <span class="keywordtype">int</span> n_frames = 0, n_tracks = 0;</div><div class="line"></div><div class="line">    <span class="comment">// extract data from text file</span></div><div class="line"></div><div class="line">    vector&lt;vector&lt;Vec2d&gt; &gt; tracks;</div><div class="line">    <span class="keywordflow">for</span> ( ; getline(myfile,line_str); ++n_tracks)</div><div class="line">    {</div><div class="line">      istringstream <a class="code" href="../../d6/d6e/group__imgproc__draw.html#ga7078a9fae8c7e7d13d24dac2520ae4a2">line</a>(line_str);</div><div class="line"></div><div class="line">      vector&lt;Vec2d&gt; track;</div><div class="line">      <span class="keywordflow">for</span> ( n_frames = 0; line &gt;&gt; x &gt;&gt; y; ++n_frames)</div><div class="line">      {</div><div class="line">        <span class="keywordflow">if</span> ( x &gt; 0 &amp;&amp; y &gt; 0)</div><div class="line">          track.push_back(<a class="code" href="../../dc/d84/group__core__basic.html#gaf20d857c2077c986d3b303e3d58bbc54">Vec2d</a>(x,y));</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">          track.push_back(<a class="code" href="../../dc/d84/group__core__basic.html#gaf20d857c2077c986d3b303e3d58bbc54">Vec2d</a>(-1));</div><div class="line">      }</div><div class="line">      tracks.push_back(track);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// embed data in reconstruction api format</span></div><div class="line"></div><div class="line">    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; n_frames; ++i)</div><div class="line">    {</div><div class="line">      <a class="code" href="../../df/dfc/classcv_1_1Mat__.html">Mat_&lt;double&gt;</a> frame(2, n_tracks);</div><div class="line"></div><div class="line">      <span class="keywordflow">for</span> (<span class="keywordtype">int</span> j = 0; j &lt; n_tracks; ++j)</div><div class="line">      {</div><div class="line">        frame(0,j) = tracks[j][i][0];</div><div class="line">        frame(1,j) = tracks[j][i][1];</div><div class="line">      }</div><div class="line">      points2d.push_back(<a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>(frame));</div><div class="line">    }</div><div class="line"></div><div class="line">    myfile.close();</div><div class="line">  }</div><div class="line"></div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">/* Keyboard callback to control 3D visualization</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"><span class="keywordtype">bool</span> camera_pov = <span class="keyword">false</span>;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> keyboard_callback(<span class="keyword">const</span> <a class="code" href="../../d3/d06/classcv_1_1viz_1_1KeyboardEvent.html">viz::KeyboardEvent</a> &amp;event, <span class="keywordtype">void</span>* cookie)</div><div class="line">{</div><div class="line">  <span class="keywordflow">if</span> ( event.<a class="code" href="../../d3/d06/classcv_1_1viz_1_1KeyboardEvent.html#a6397bf651511d452f26a700df2df7381">action</a> == 0 &amp;&amp;!event.<a class="code" href="../../d3/d06/classcv_1_1viz_1_1KeyboardEvent.html#a45265d0feab99428177831a24374854f">symbol</a>.compare(<span class="stringliteral">&quot;s&quot;</span>) )</div><div class="line">    camera_pov = !camera_pov;</div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">/* Sample main code</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv)</div><div class="line">{</div><div class="line">  <span class="comment">// Read input parameters</span></div><div class="line"></div><div class="line">  <span class="keywordflow">if</span> ( argc != 5 )</div><div class="line">  {</div><div class="line">    help();</div><div class="line">    exit(0);</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Read 2D points from text file</span></div><div class="line">  std::vector&lt;Mat&gt; points2d;</div><div class="line">  parser_2D_tracks( argv[1], points2d );</div><div class="line"></div><div class="line">  <span class="comment">// Set the camera calibration matrix</span></div><div class="line">  <span class="keyword">const</span> <span class="keywordtype">double</span> f  = atof(argv[2]),</div><div class="line">               cx = atof(argv[3]), cy = atof(argv[4]);</div><div class="line"></div><div class="line">  <a class="code" href="../../de/de1/classcv_1_1Matx.html">Matx33d</a> K = <a class="code" href="../../dc/d84/group__core__basic.html#gaff0100a48f049fb15584a4a657eae838">Matx33d</a>( f, 0, cx,</div><div class="line">                       0, f, cy,</div><div class="line">                       0, 0,  1);</div><div class="line"></div><div class="line"></div><div class="line">  <span class="keywordtype">bool</span> is_projective = <span class="keyword">true</span>;</div><div class="line">  vector&lt;Mat&gt; Rs_est, ts_est, points3d_estimated;</div><div class="line">  <a class="code" href="../../da/db5/group__reconstruction.html#ga279c084302ae1d7541d458e4b23fabd3">reconstruct</a>(points2d, Rs_est, ts_est, K, points3d_estimated, is_projective);</div><div class="line"></div><div class="line">  <span class="comment">// Print output</span></div><div class="line"></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;\n----------------------------\n&quot;</span> &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Reconstruction: &quot;</span> &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;============================&quot;</span> &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Estimated 3D points: &quot;</span> &lt;&lt; points3d_estimated.size() &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Estimated cameras: &quot;</span> &lt;&lt; Rs_est.size() &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Refined intrinsics: &quot;</span> &lt;&lt; endl &lt;&lt; K &lt;&lt; endl &lt;&lt; endl;</div><div class="line"></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;3D Visualization: &quot;</span> &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;============================&quot;</span> &lt;&lt; endl;</div><div class="line"></div><div class="line"></div><div class="line">  <a class="code" href="../../d6/d32/classcv_1_1viz_1_1Viz3d.html">viz::Viz3d</a> window_est(<span class="stringliteral">&quot;Estimation Coordinate Frame&quot;</span>);</div><div class="line">             window_est.setBackgroundColor(); <span class="comment">// black by default</span></div><div class="line">             window_est.registerKeyboardCallback(&amp;keyboard_callback);</div><div class="line"></div><div class="line">  <span class="comment">// Create the pointcloud</span></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Recovering points  ... &quot;</span>;</div><div class="line"></div><div class="line">  <span class="comment">// recover estimated points3d</span></div><div class="line">  vector&lt;Vec3f&gt; point_cloud_est;</div><div class="line">  <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; points3d_estimated.size(); ++i)</div><div class="line">    point_cloud_est.push_back(<a class="code" href="../../d6/dcf/classcv_1_1Vec.html">Vec3f</a>(points3d_estimated[i]));</div><div class="line"></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;[DONE]&quot;</span> &lt;&lt; endl;</div><div class="line"></div><div class="line"></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Recovering cameras ... &quot;</span>;</div><div class="line"></div><div class="line">  vector&lt;Affine3d&gt; path_est;</div><div class="line">  <span class="keywordflow">for</span> (<span class="keywordtype">size_t</span> i = 0; i &lt; Rs_est.size(); ++i)</div><div class="line">    path_est.push_back(<a class="code" href="../../dd/d99/classcv_1_1Affine3.html">Affine3d</a>(Rs_est[i],ts_est[i]));</div><div class="line"></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;[DONE]&quot;</span> &lt;&lt; endl;</div><div class="line"></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Rendering Trajectory  ... &quot;</span>;</div><div class="line"></div><div class="line">  cout &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;Press:                       &quot;</span> &lt;&lt; endl;</div><div class="line">  cout &lt;&lt;         <span class="stringliteral">&quot; &#39;s&#39; to switch the camera pov&quot;</span> &lt;&lt; endl;</div><div class="line">  cout &lt;&lt;         <span class="stringliteral">&quot; &#39;q&#39; to close the windows    &quot;</span> &lt;&lt; endl;</div><div class="line"></div><div class="line"></div><div class="line">  <span class="keywordflow">if</span> ( path_est.size() &gt; 0 )</div><div class="line">  {</div><div class="line">    <span class="comment">// animated trajectory</span></div><div class="line">    <span class="keywordtype">int</span> idx = 0, forw = -1, n = <span class="keyword">static_cast&lt;</span><span class="keywordtype">int</span><span class="keyword">&gt;</span>(path_est.size());</div><div class="line"></div><div class="line">    <span class="keywordflow">while</span>(!window_est.wasStopped())</div><div class="line">    {</div><div class="line">      <span class="keywordflow">for</span> (<span class="keywordtype">size_t</span> i = 0; i &lt; point_cloud_est.size(); ++i)</div><div class="line">      {</div><div class="line">        <a class="code" href="../../d6/dcf/classcv_1_1Vec.html">Vec3d</a> point = point_cloud_est[i];</div><div class="line">        <a class="code" href="../../dd/d99/classcv_1_1Affine3.html">Affine3d</a> point_pose(Mat::eye(3,3,<a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga30a562691cc5987bc88eb7bb7a8faf2b">CV_64F</a>), point);</div><div class="line"></div><div class="line">        <span class="keywordtype">char</span> buffer[50];</div><div class="line">        sprintf (buffer, <span class="stringliteral">&quot;%d&quot;</span>, static_cast&lt;int&gt;(i));</div><div class="line"></div><div class="line">        <a class="code" href="../../d2/d17/classcv_1_1viz_1_1WCube.html">viz::WCube</a> cube_widget(<a class="code" href="../../dc/d84/group__core__basic.html#ga3d79ceeb4419bccd0308dfdf1cd31435">Point3f</a>(0.1,0.1,0.0), <a class="code" href="../../dc/d84/group__core__basic.html#ga3d79ceeb4419bccd0308dfdf1cd31435">Point3f</a>(0.0,0.0,-0.1), <span class="keyword">true</span>, viz::Color::blue());</div><div class="line">                   cube_widget.setRenderingProperty(<a class="code" href="../../dc/d5c/group__viz__widget.html#ggae4df8152c2d8639b915eccd0bb90f8aca06fc87e04c15fbfad2977314751a8738">viz::LINE_WIDTH</a>, 2.0);</div><div class="line">        window_est.showWidget(<span class="stringliteral">&quot;Cube&quot;</span>+<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>(buffer), cube_widget, point_pose);</div><div class="line">      }</div><div class="line"></div><div class="line">      <a class="code" href="../../dd/d99/classcv_1_1Affine3.html">Affine3d</a> cam_pose = path_est[idx];</div><div class="line"></div><div class="line">      <a class="code" href="../../d6/dcc/classcv_1_1viz_1_1WCameraPosition.html">viz::WCameraPosition</a> cpw(0.25); <span class="comment">// Coordinate axes</span></div><div class="line">      <a class="code" href="../../d6/dcc/classcv_1_1viz_1_1WCameraPosition.html">viz::WCameraPosition</a> cpw_frustum(K, 0.3, viz::Color::yellow()); <span class="comment">// Camera frustum</span></div><div class="line"></div><div class="line">      <span class="keywordflow">if</span> ( camera_pov )</div><div class="line">        window_est.setViewerPose(cam_pose);</div><div class="line">      <span class="keywordflow">else</span></div><div class="line">      {</div><div class="line">        <span class="comment">// render complete trajectory</span></div><div class="line">        window_est.showWidget(<span class="stringliteral">&quot;cameras_frames_and_lines_est&quot;</span>, <a class="code" href="../../d0/da3/classcv_1_1viz_1_1WTrajectory.html">viz::WTrajectory</a>(path_est, viz::WTrajectory::PATH, 1.0, viz::Color::green()));</div><div class="line"></div><div class="line">        window_est.showWidget(<span class="stringliteral">&quot;CPW&quot;</span>, cpw, cam_pose);</div><div class="line">        window_est.showWidget(<span class="stringliteral">&quot;CPW_FRUSTUM&quot;</span>, cpw_frustum, cam_pose);</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="comment">// update trajectory index (spring effect)</span></div><div class="line">      forw *= (idx==n || idx==0) ? -1: 1; idx += forw;</div><div class="line"></div><div class="line">      <span class="comment">// frame rate 1s</span></div><div class="line">      window_est.spinOnce(1, <span class="keyword">true</span>);</div><div class="line">      window_est.removeAllWidgets();</div><div class="line">    }</div><div class="line"></div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --><h2>Explanation </h2>
<p>Firstly, we need to load the file containing the 2d points tracked over all the frames and construct the container to feed the reconstruction api. In this case the tracked 2d points will have the following structure, a vector of 2d points array, where each inner array represents a different frame. Every frame is composed by a list of 2d points which e.g. the first point in frame 1 is the same point in frame 2. If there is no point in a frame the assigned value will be (-1,-1):</p>
<div class="fragment"><div class="line"><span class="comment">/* Build the following structure data</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *            frame1           frame2           frameN</span></div><div class="line"><span class="comment"> *  track1 | (x11,y11) | -&gt; | (x12,y12) | -&gt; | (x1N,y1N) |</span></div><div class="line"><span class="comment"> *  track2 | (x21,y11) | -&gt; | (x22,y22) | -&gt; | (x2N,y2N) |</span></div><div class="line"><span class="comment"> *  trackN | (xN1,yN1) | -&gt; | (xN2,yN2) | -&gt; | (xNN,yNN) |</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *  In case a marker (x,y) does not appear in a frame its</span></div><div class="line"><span class="comment"> *  values will be (-1,-1).</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"> ...</div><div class="line"></div><div class="line">for (<span class="keywordtype">int</span> i = 0; i &lt; n_frames; ++i)</div><div class="line">{</div><div class="line">  Mat_&lt;double&gt; frame(2, n_tracks);</div><div class="line"></div><div class="line">  <span class="keywordflow">for</span> (<span class="keywordtype">int</span> j = 0; j &lt; n_tracks; ++j)</div><div class="line">  {</div><div class="line">    frame(0,j) = tracks[j][i][0];</div><div class="line">    frame(1,j) = tracks[j][i][1];</div><div class="line">  }</div><div class="line">  points2d.push_back(Mat(frame));</div><div class="line">}</div></div><!-- fragment --><p>Secondly, the built container will be used to feed the reconstruction api. It is important outline that the estimated results must be stored in a vector&lt;Mat&gt;:</p>
<div class="fragment"><div class="line"><span class="keywordtype">bool</span> is_projective = <span class="keyword">true</span>;</div><div class="line">vector&lt;Mat&gt; Rs_est, ts_est, points3d_estimated;</div><div class="line"><a class="code" href="../../da/db5/group__reconstruction.html#ga279c084302ae1d7541d458e4b23fabd3">reconstruct</a>(points2d, Rs_est, ts_est, K, points3d_estimated, is_projective);</div><div class="line"></div><div class="line"><span class="comment">// Print output</span></div><div class="line"></div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;\n----------------------------\n&quot;</span> &lt;&lt; endl;</div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;Reconstruction: &quot;</span> &lt;&lt; endl;</div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;============================&quot;</span> &lt;&lt; endl;</div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;Estimated 3D points: &quot;</span> &lt;&lt; points3d_estimated.size() &lt;&lt; endl;</div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;Estimated cameras: &quot;</span> &lt;&lt; Rs_est.size() &lt;&lt; endl;</div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;Refined intrinsics: &quot;</span> &lt;&lt; endl &lt;&lt; K &lt;&lt; endl &lt;&lt; endl;</div></div><!-- fragment --><p>Finally, the obtained results will be shown in Viz, in this case reproducing the camera with an oscillation effect.</p>
<h2>Usage and Results </h2>
<p>In order to run this sample we need to specify the path to the tracked points file, the focal length of the camera in addition to the center projection coordinates (in pixels). You can find a sample file in samples/data/desktop_trakcks.txt</p>
<div class="fragment"><div class="line">./example_sfm_trajectory_reconstruction desktop_tracks.txt 1914 640 360</div></div><!-- fragment --><p>The following picture shows the obtained camera motion obtained from the tracked 2d points:</p>
<div class="image">
<img src="../../desktop_trajectory.png" alt="desktop_trajectory.png"/>
</div>
 </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:39 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
